<template>
    <el-image :style="[style, { cursor: 'pointer' }]" :src="src" :fit="fit as any" @click="onBig">
        <!-- 占位内容 -->
        <template #placeholder>
            <div class="image-slot">
                <img :src="defaultImage" width="40px" />
            </div>
        </template>
        <!-- 错误内容 -->
        <template #error>
            <div class="image-slot">
                <lemon-icon icon="IconPicture" />
            </div>
        </template>
    </el-image>

    <!-- 图片预览层 -->
    <teleport to="body" v-if="dialogShow">
        <div class="image-preview-overlay" @click="closePreview" @wheel="handleWheel" @mousedown="startDrag" @mousemove="onDrag" @mouseup="stopDrag" @mouseleave="stopDrag">
            <img :src="src" class="preview-image animate__animated animate__zoomIn" :style="imageStyle" @load="handleImageLoad" @click.stop />

            <!-- 缩放提示 -->
            <div class="zoom-hint" v-if="showZoomHint">缩放: {{ Math.round(scale * 100) }}%</div>

            <!-- 关闭按钮 -->
            <div class="close-btn" @click="closePreview">
                <el-icon><Close /></el-icon>
            </div>
        </div>
    </teleport>
</template>

<script setup lang="ts">
import { ref, inject, computed, onUnmounted, onMounted } from "vue";
import defaultImage from "@/assets/img/default-image.png";
import { Close } from "@element-plus/icons-vue";

//获取自定义全局方法
const { emitter } = inject<any>("method");

//父传子
interface Props {
    src?: string | undefined | "";
    style?: object | string | null;
    fit?: string | null;
    title?: string | null;
}
const props = withDefaults(defineProps<Props>(), {
    src: undefined,
    style: () => ({ width: "100px", height: "100px" }),
    fit: "fill",
    title: null,
});

// 缩放相关状态
const scale = ref(1);
const minScale = ref(0.1);
const maxScale = ref(5);
const position = ref({ x: 0, y: 0 });
const isDragging = ref(false);
const dragStart = ref({ x: 0, y: 0 });
const showZoomHint = ref(false);
const hintTimer = ref<number>();

// 图片样式
const imageStyle = computed(() => ({
    transform: `scale(${scale.value}) translate(${position.value.x}px, ${position.value.y}px)`,
    cursor: isDragging.value ? "grabbing" : scale.value > 1 ? "grab" : "default",
    transition: isDragging.value ? "none" : "transform 0.1s ease",
}));

const dialogShow = ref(false);

// 鼠标滚轮缩放
const handleWheel = (event: WheelEvent) => {
    event.preventDefault();

    const delta = -Math.sign(event.deltaY); // 向下滚动缩小，向上滚动放大
    const zoomFactor = 0.1;

    if (delta > 0) {
        zoomIn(zoomFactor);
    } else {
        zoomOut(zoomFactor);
    }

    // 显示缩放提示
    showZoomHint.value = true;
    clearTimeout(hintTimer.value);
    hintTimer.value = setTimeout(() => {
        showZoomHint.value = false;
    }, 1500);
};

// 放大
const zoomIn = (factor = 0.1) => {
    const newScale = Math.min(scale.value + factor, maxScale.value);
    if (newScale !== scale.value) {
        scale.value = newScale;
    }
};

// 缩小
const zoomOut = (factor = 0.1) => {
    const newScale = Math.max(scale.value - factor, minScale.value);
    if (newScale !== scale.value) {
        scale.value = newScale;
    }
};

// 重置缩放和位置
const resetZoom = () => {
    scale.value = 1;
    position.value = { x: 0, y: 0 };
};

// 拖拽功能
const startDrag = (event: MouseEvent) => {
    if (scale.value <= 1) return; // 只有在缩放状态下才能拖拽

    isDragging.value = true;
    dragStart.value = {
        x: event.clientX - position.value.x,
        y: event.clientY - position.value.y,
    };
};

const onDrag = (event: MouseEvent) => {
    if (!isDragging.value) return;

    position.value = {
        x: event.clientX - dragStart.value.x,
        y: event.clientY - dragStart.value.y,
    };
};

const stopDrag = () => {
    isDragging.value = false;
};

//计算图片大小
const handleImageLoad = (_event: any) => {
    resetZoom();
};

//图片放大
const onBig = () => {
    if (props.src) {
        dialogShow.value = true;
        // 禁止背景滚动
        document.body.style.overflow = "hidden";
    } else {
        emitter.emit("msg-error", "图片地址为空，无法放大！");
    }
};

// 关闭预览
const closePreview = () => {
    dialogShow.value = false;
    resetZoom();
    // 恢复背景滚动
    document.body.style.overflow = "";
};

// 键盘事件
const handleKeyDown = (event: KeyboardEvent) => {
    if (!dialogShow.value) return;

    switch (event.key) {
        case "Escape":
            closePreview();
            break;
        case "=":
        case "+":
            event.preventDefault();
            zoomIn();
            break;
        case "-":
            event.preventDefault();
            zoomOut();
            break;
        case "0":
            event.preventDefault();
            resetZoom();
            break;
    }
};

// 添加键盘事件监听
onMounted(() => {
    document.addEventListener("keydown", handleKeyDown);
});

// 组件卸载时移除事件监听
onUnmounted(() => {
    document.removeEventListener("keydown", handleKeyDown);
    clearTimeout(hintTimer.value);
    // 确保恢复滚动
    document.body.style.overflow = "";
});
</script>

<style scoped lang="less">
.image-preview-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    background: rgba(0, 0, 0, 0.4);
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 2147483647;
    cursor: pointer;
    background-size: 20px 20px;
    background-position: 0 0, 0 10px, 10px -10px, -10px 0px;
    .preview-image {
        max-width: 70vw;
        max-height: 70vh;
        object-fit: contain;
        display: block;
        width: auto;
        height: auto;
        user-select: none;
        -webkit-user-drag: none;
        transform-origin: center center;
    }

    .zoom-hint {
        position: absolute;
        top: 20px;
        left: 50%;
        transform: translateX(-50%);
        background: rgba(0, 0, 0, 0.9);
        color: white;
        padding: 8px 16px;
        border-radius: 20px;
        font-size: 14px;
        backdrop-filter: blur(10px);
        z-index: 2147483647;
        border: 1px solid rgba(255, 255, 255, 0.3);
    }

    .close-btn {
        position: absolute;
        top: 20px;
        right: 20px;
        width: 40px;
        height: 40px;
        background: rgba(0, 0, 0, 0.9);
        color: white;
        border-radius: 50%;
        display: flex;
        align-items: center;
        justify-content: center;
        cursor: pointer;
        z-index: 2147483647;
        backdrop-filter: blur(10px);
        transition: all 0.3s ease;
        border: 1px solid rgba(255, 255, 255, 0.3);

        &:hover {
            background: rgba(35, 79, 111, 0.6);
            transform: scale(1.1);
            border-color: rgba(255, 255, 255, 0.6);
        }
    }
}
</style>
